package com.main.service;


import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.main.dao.UserDAO;
import com.main.mail.GenericoMailSender;
import com.web.security.CustomUser;
import com.web.util.GenericoUtil;

@Service
@Transactional(readOnly = true)
public class CustomUserDetailsService  extends AbstractUserDetailsAuthenticationProvider /*implements UserDetailsService*/{
	
	@Autowired
	private UserDAO userRepository;

	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		// TODO Auto-generated method stub
		
	}

	@Override
	protected UserDetails retrieveUser(String username,
			UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		try {
//			logger.info("diana: " + GenericoUtil.getBase64Encode("coco91"));
//			logger.info("carmen: " + GenericoUtil.getBase64Encode("titi91"));
//			logger.info("gerardo: " + GenericoUtil.getBase64Encode("fisica"));
//			logger.info("chepe: " + GenericoUtil.getBase64Encode("amigo91"));
//			logger.info("pati: " + GenericoUtil.getBase64Encode("tosti91"));
//			logger.info("hector: " + GenericoUtil.getBase64Encode("taber91"));
//			logger.info("emilio: " + GenericoUtil.getBase64Encode("emilio"));
//			logger.info("natividad: " + GenericoUtil.getBase64Encode("natividad"));
//			logger.info("lecter: " + GenericoUtil.getBase64Encode("lecter91"));
//			logger.info("javier: " + GenericoUtil.getBase64Encode("javier"));
//			logger.info("ADMINISTRADOR: " + GenericoUtil.getBase64Encode("123456"));
//			logger.info("sales" + GenericoUtil.getBase64Decode("EGdPlS5Ox7QITnnf1dVw7+Oiup36HFfpENLkipWhSAYfjur51scKxMyIcNHo405nZE0pwQNYLiDK3pndhijtQQ=="));
//			logger.info("ntesorero  " + GenericoUtil.getBase64Decode("Ym5SbGMyOXlaWEp2"));
//			logger.info("ana  " + GenericoUtil.getBase64Decode("WlcxcGJtVnQ="));
//			logger.info("lrivera  " + GenericoUtil.getBase64Decode("TVRJek5EVTI="));
//			logger.info("gcalixto  " + GenericoUtil.getBase64Decode("WjJOaGJHbDRkRzg9"));
//			logger.info("patricia  " + GenericoUtil.getBase64Decode("TVRJek5EVT0="));
			
			if (authentication.getCredentials() == null || username.length() == 0)
				throw new BadCredentialsException("DATOS DE USUARIO INCOMPLETOS");

			WebAuthenticationDetails webAuthenticationDetails = (WebAuthenticationDetails) authentication.getDetails();
			String password = authentication.getCredentials().toString();
//			String decodedUserName = new String( Base64.decodeBase64(EquifaxUtil.getKycWebProperty(EquifaxUtil.EXPERTO_CONFIGURACION)) );
//			String decodedPassword = new String( Base64.decodeBase64(EquifaxUtil.getKycWebProperty(EquifaxUtil.EXPERTO_CONFIGURACION_1)) );
//			String decodedPasswordYYYYMMDD = decodedPassword ;//+ EquifaxUtil.getFechaAsDDMMYYYY(new Date());
//			String decodeSystemWsUser = new String(Base64.decodeBase64(EquifaxUtil.getKycWebProperty(EquifaxUtil.KYC_SISTEMA_USUARIO_BUREAU)));
//			String decodeSystemWsClave = new String(Base64.decodeBase64(EquifaxUtil.getKycWebProperty(EquifaxUtil.KYC_SISTEMA_CLAVE_BUREAU)));
//			if (username.equalsIgnoreCase(decodedUserName) &&
//					password.equalsIgnoreCase(decodedPasswordYYYYMMDD)) {
//				List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_USUARIO));
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_PERSONA_FISICA));
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_PERSONA_JURIDICA));
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_ADMINISTRADOR_EMPLEADOS));
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_ADMINISTRADOR));
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_DOCUMENTO));
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_CONSULTAS));
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_CONFIGURACION));
//				return new KycUserDetails(username, password,
//						true, true, true, true, authorities, "0","",null,EquifaxUtil.KYC_BUREAU_COD_EMPRESA ,"","",decodeSystemWsUser,decodeSystemWsClave, "FULL");
//			}else if(password.equalsIgnoreCase(decodedPassword)){
//				List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_USUARIO));
//				//authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_CONFIGURACION));
//				return new KycUserDetails(username, password,
//						true, true, true, true, authorities,"0","",null,EquifaxUtil.KYC_BUREAU_COD_EMPRESA ,"","",decodeSystemWsUser,decodeSystemWsClave, "FULL");
//			}


//			SgdUsuario sgdUsuario = DBContext.getSgdUsuarioDao().findActiveUserWithPassword(username, password);
//			if (sgdUsuario != null) {
//				List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_USUARIO));
//				authorities.add(new GrantedAuthorityImpl(EquifaxUtil.ROLE_FACTURACION));
//				return new KycUserDetails(username, password,
//						true, true, true, true, authorities,
//						sgdUsuario.getSgdUsuarioCambiarClave(),"", sgdUsuario , "" ,"","","","", "");
//			}
//
//			String ip = webAuthenticationDetails.getRemoteAddress();
//			if (StringUtils.isNotEmpty(username) && StringUtils.isNotEmpty(password)) {
//				return DataStreamAuthentication.doDataStreamLogin(username, password, ip);
//			}else{
//				throw new BadCredentialsException("DATOS DE USUARIO INCOMPLETOS");
//			}

			/**
			 * Mi modo de hacer el login
			 */
			String ip = webAuthenticationDetails.getRemoteAddress();
			com.main.java.User domainUser = userRepository.obtenerUsuarioActivoConContrasena(username, password);
			if (domainUser != null) {
				
			Long sucursalId = domainUser.getCtgSucursal().getCtgSucursalId();
			boolean enabled = true;
			boolean accountNonExpired = true;
			boolean credentialsNonExpired = true;
			boolean accountNonLocked = true;
			
			CustomUser cU = new CustomUser(
					domainUser.getLogin(), 
					domainUser.getPassword().toLowerCase(),
					enabled,
					accountNonExpired,
					credentialsNonExpired,
					accountNonLocked,
					getAuthorities(Integer.parseInt(domainUser.getRole().getRoleId().toString())),
					domainUser.getId(),
					userRepository.findClienteByUserId(domainUser.getId()),
					ip,
					sucursalId
					);
			userRepository.getCustomUser(cU, username);
//			GenericoMailSender.enviarMensaje("claveOlvidada " + ip);
//			String enccriptado = GenericoUtil.getBase64Encode("lecter91");
//			logger.info("123456 = " + GenericoUtil.getBase64Encode("javier"));
			return cU;
			}else{
				throw new BadCredentialsException("DATOS DE USUARIO INCORECTOS");
			}
			
			
		}catch(BadCredentialsException e){
				logger.error("retrieveUser", e);
				throw e;
			}catch(Exception e){
				logger.error("retrieveUser", e);
				throw new BadCredentialsException("Problemas al autenticar al usuario: " + e.getMessage(), e);
			}
	}
	
	/**
	 * Returns a populated {@link UserDetails} object. 
	 * The username is first retrieved from the database and then mapped to 
	 * a {@link UserDetails} object.
	 */
//	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//		try {
//			com.main.java.User domainUser = userRepository.getUser(username);
//			
//			boolean enabled = true;
//			boolean accountNonExpired = true;
//			boolean credentialsNonExpired = true;
//			boolean accountNonLocked = true;
//			
//			CustomUser cU = new CustomUser(
//					domainUser.getLogin(), 
//					domainUser.getPassword().toLowerCase(),
//					enabled,
//					accountNonExpired,
//					credentialsNonExpired,
//					accountNonLocked,
//					getAuthorities(Integer.parseInt(domainUser.getRole().getRoleId().toString())),
//					domainUser.getId(),
//					userRepository.findClienteByUserId(domainUser.getId())
//					);
//			userRepository.getCustomUser(cU, username);
//			
//			return new CustomUser(
//					domainUser.getLogin(), 
//					domainUser.getPassword().toLowerCase(),
//					enabled,
//					accountNonExpired,
//					credentialsNonExpired,
//					accountNonLocked,
//					getAuthorities(Integer.parseInt(domainUser.getRole().getRoleId().toString())),
//					domainUser.getId(),
//					userRepository.findClienteByUserId(domainUser.getId())
//					);
//			
//		} catch (Exception e) {
//			throw new RuntimeException(e);
//		}
//	}
	
	/**
	 * Retrieves a collection of {@link GrantedAuthority} based on a numerical role
	 * @param role the numerical role
	 * @return a collection of {@link GrantedAuthority
	 */
	public Collection<? extends GrantedAuthority> getAuthorities(Integer role) {
		List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
		return authList;
	}
	
	/**
	 * Converts a numerical role to an equivalent list of roles
	 * @param role the numerical role
	 * @return list of roles as as a list of {@link String}
	 */
	public List<String> getRoles(Integer role) {
		List<String> roles = new ArrayList<String>();
		
		if (role.intValue() == 1) {
			roles.add("ROLE_EMPLEADO");
			roles.add("ROLE_MODERATOR");
			roles.add("ROLE_ADMIN");
			roles.add("ROLE_SECRETARIA");
			roles.add("ROLE_VENDEDOR");
			roles.add("ROLE_INSTALADOR");
			roles.add("ROLE_JEFE_TALLER");
			roles.add("ROLE_ASISTENTE_GERENTE");
			roles.add("ROLE_GERENTE");
			roles.add("ROLE_ADMINISTRADOR");
			
		} else if (role.intValue() == 2) {
			roles.add("ROLE_MODERATOR");
		} else if (role.intValue() == 3) {
			roles.add("ROLE_EMPLEADO");
		}else if (role.intValue() == 4) {
			roles.add("ROLE_CLIENTE");
		}else if (role.intValue() == 5) {
			roles.add("ROLE_SECRETARIA");
		}else if (role.intValue() == 6) {
			roles.add("ROLE_VENDEDOR");
		}else if (role.intValue() == 7) {
			roles.add("ROLE_INSTALADOR");
		}else if (role.intValue() == 8) {
			roles.add("ROLE_JEFE_TALLER");
		}else if (role.intValue() == 9) {
			roles.add("ROLE_ASISTENTE_GERENTE");
		}else if (role.intValue() == 10) {
			roles.add("ROLE_GERENTE");
		}
		
		return roles;
	}
	
	/**
	 * Wraps {@link String} roles to {@link SimpleGrantedAuthority} objects
	 * @param roles {@link String} of roles
	 * @return list of granted authorities
	 */
	public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
		List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
		for (String role : roles) {
			authorities.add(new SimpleGrantedAuthority(role));
		}
		return authorities;
	}

	/*@Override
	public UserDetails loadUserByUsername(String arg0)
			throws UsernameNotFoundException {
		// TODO Auto-generated method stub
		return null;
	}*/

	
}
